#include <xp/net/socket.h>
#include <xp/bas/string.h>
#include <xp/bas/mstring.h>
#include <xp/bas/memory.h>
#include <xp/bas/locale.h>
#include <xp/bas/stdlib.h>
#include <xp/bas/stdio.h>
#include <xp/bas/time.h>
#include <xp/bas/errno.h>
#include <xp/bas/signal.h>
#include <xp/bas/endian.h>

#ifndef _WIN32
	#include <arpa/inet.h>
#endif

#ifdef __linux
	#include <mcheck.h>
#endif

int quit = 0;

void set_quit (int sig)
{
	xp_signal (SIGINT, SIG_IGN);
	quit = 1;
	xp_signal (SIGINT, set_quit);
}

int xp_main (int argc, xp_char_t* argv[])
{
	int handle;
	xp_uint16_t port;
	struct sockaddr_in to;
	struct sockaddr_in from;
	xp_time_t start, end;
	const char* msg = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";

	long max;
	long zzz = 0;

#ifdef __linux
	mtrace ();
#endif

	xp_setlocale ();
	xp_signal (SIGINT, set_quit);

	if (argc != 4) {
		xp_printf (XP_TEXT("usage: %s host port max\n"), argv[0]);
		return -1;
	}

	if (xp_sckstartup() == -1) {
		xp_printf (XP_TEXT("can't startup socket subsystem\n"));
		return -1;
	}

	if ((handle = xp_sckopen(PF_INET, SOCK_DGRAM, 0)) == -1) {
		xp_printf (XP_TEXT("can't create socket\n"));
		xp_sckcleanup ();
		return -1;
	}

	XP_STRTOI (max, argv[3], XP_NULL, 10);
	XP_STRTOI (port, argv[2], XP_NULL, 10);

	xp_memset (&to, 0, xp_sizeof(to));
	to.sin_family = AF_INET;
#ifdef XP_CHAR_IS_WCHAR
	{
		xp_mchar_t host[1000];
		xp_wcstomcs (argv[1], host, xp_countof(host));
		to.sin_addr.s_addr = inet_addr (host);
	}
#else
	to.sin_addr.s_addr = inet_addr (argv[1]);
#endif
	to.sin_port = xp_hton16 (port);

	xp_gettime (&start);
	while (!quit && zzz < max) {
		xp_scklen_t from_len;
		xp_byte_t buf[65535];
		xp_ssize_t n;

		from_len = xp_sizeof(from);

		xp_scksendto (handle, msg, xp_mstrlen(msg), 0, (struct sockaddr*)&to, xp_sizeof(to), -1);

		n = xp_sckrecvfrom (handle, buf, xp_sizeof(buf), 0, (struct sockaddr*)&from, &from_len, 3000);
		if (n == -1 && xp_geterrno() == XP_ETIMEDOUT) {
			xp_printf (XP_TEXT("timed out...\n"));
		}
		//buf[n] = '\0';
		//printf ("%s\n", buf);
		zzz++;
	}
	xp_gettime (&end);

	xp_sckclose (handle);
	xp_sckcleanup ();

	xp_printf (XP_TEXT("zzz = %lu, max = %lu, lapse = %lu\n"), 
		zzz, max, (unsigned long)((end - start) / 1000));
#ifdef __linux
	muntrace ();
#endif
	return 0;
}
